using System;
using UnityEngine.Rendering.Universal.Internal;
using UnityEngine.Experimental.Rendering;

namespace UnityEngine.Rendering.Universal
{
    [Serializable, VolumeComponentMenu("Post-processing/Blur")]
    public class Blur : VolumeComponent, IPostProcessComponent
    {
                  
        public BoolParameter activeOn = new BoolParameter(false, true);      
        //public ClampedFloatParameter stepOffset = new ClampedFloatParameter(1.5f, 1, 10f, false);
        public ClampedIntParameter iteration = new ClampedIntParameter(3, 1, 5, false);
        public ClampedFloatParameter blurRadius = new ClampedFloatParameter(1.5f, 0, 8f, false);
        public ClampedIntParameter RTDownScaling = new ClampedIntParameter(4, 1, 6, false);
       
          
        static readonly int m_ParamsId = Shader.PropertyToID("_Params");
        static readonly int m_StepOffsetId = Shader.PropertyToID("_StepOffset");

        GraphicsFormat m_DefaultHDRFormat;

        static readonly int m_BufferRT1 = Shader.PropertyToID("_BufferRT1");
        static readonly int m_BufferRT2 = Shader.PropertyToID("_BufferRT2");

        public bool IsActive()
        {
            return activeOn.value;
        }

        public bool IsTileCompatible()
        {
            return false;
        }

        public void Setup()
        {
            if (SystemInfo.IsFormatSupported(GraphicsFormat.B10G11R11_UFloatPack32, FormatUsage.Linear | FormatUsage.Render))
                m_DefaultHDRFormat = GraphicsFormat.B10G11R11_UFloatPack32;
            else
                m_DefaultHDRFormat = QualitySettings.activeColorSpace == ColorSpace.Linear ? GraphicsFormat.R8G8B8A8_SRGB : GraphicsFormat.R8G8B8A8_UNorm;
        }

        public void Render(CommandBuffer cmd, Material material, RTHandle source, RTHandle destination, RenderTextureDescriptor descriptor)
        {          
            material.SetVector(m_ParamsId, new Vector4(iteration.value, blurRadius.value, 1f / descriptor.width, 1f / descriptor.height));
            int RTWidth = Mathf.FloorToInt(descriptor.width / RTDownScaling.value);
            int RTHeight = Mathf.FloorToInt(descriptor.height / RTDownScaling.value);
            cmd.GetTemporaryRT(m_BufferRT1, RTWidth, RTHeight, 0, FilterMode.Bilinear, m_DefaultHDRFormat);
            cmd.GetTemporaryRT(m_BufferRT2, RTWidth, RTHeight, 0, FilterMode.Bilinear, m_DefaultHDRFormat);
        

            bool needSwitch = true;
            for (int i = 0; i < iteration.value - 1; i++)
            {
                material.SetFloat(m_StepOffsetId, blurRadius.value);
                cmd.Blit(needSwitch ? m_BufferRT1 : m_BufferRT2, needSwitch ? m_BufferRT2 : m_BufferRT1, material, 0);
                needSwitch = !needSwitch;
            }

            material.SetFloat(m_StepOffsetId, blurRadius.value);
            cmd.Blit(m_BufferRT1, BlitDstDiscardContent(cmd, destination), material, 0);
            cmd.ReleaseTemporaryRT(m_BufferRT1);
            cmd.ReleaseTemporaryRT(m_BufferRT2);
        }

        /// <summary>
        /// 外部访问接口
        /// </summary>
        /// <param name="_BlurRadius"></param>
        /// <param name="_Iteration">值越小性能越好，但效果会差一些，一般6-8即可</param>
        /// <param name="_CenterX"></param>
        /// <param name="_CenterY"></param>
        /// <param name="_AreaSize"></param>
        /// <param name="_SmoothWidth"></param>
        /// <param name="type"></param>
        public void UpdateVector6(float _BlurRadius,float _RTDownScaling,float _Iteration = 6,float _CenterY = 0.0f, float _AreaSize = 0.5f, float _SmoothWidth = 0.2f, int type = 0)
        {
            blurRadius.overrideState = true;
            blurRadius.value = _BlurRadius;

            iteration.overrideState = true;
            iteration.value =(int) _Iteration; 

            RTDownScaling.overrideState = true;
            RTDownScaling.value =(int) _RTDownScaling;        
        }

        /// <summary>
        /// 是否启用
        /// </summary>
        /// <param name="value"></param>
        public void SetActive(bool value)
        {
            activeOn.overrideState = true;
            activeOn.value = value;
        }


        public BuiltinRenderTextureType BlitDstDiscardContent(CommandBuffer cmd, RenderTargetIdentifier rt)
        {
            //只保留color，把depth丢掉，节约带宽
            cmd.SetRenderTarget(new RenderTargetIdentifier(rt, 0, CubemapFace.Unknown, -1),
                RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store,
                RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare);
            return BuiltinRenderTextureType.CurrentActive;
        }
    }
}
